/**
 * 拾取物体
 */

import * as THREE from '../threejs/build/three.module.js';

import { Utils } from './Utils.js';
import { createMsg } from './Msg.js';

let utils = new Utils();
let msg = createMsg();

class Ray {
    constructor(objects, camera, scene, searchKey, callback) {
        this.objects = objects;
        this.camera = camera;
        this.scene = scene;
        this.searchKey = searchKey;
        this.callback = callback;

        this._oldDistance = 1;
        this._oldCameraPos = { x: camera.position.x, y: camera.position.y, z: camera.position.z };

        this.viewerContainerId = '#threeCanvas';
        this.viewerContainer = $(this.viewerContainerId)[0];

        this._isRay = false;
    }

    start() {
        if (!this._isRay) {
            this._isRay = true;
            this.viewerContainer.addEventListener('click', e => this.ray(e));
            this.viewerContainer.addEventListener('mousedown', () => this.mousedown());
            this.viewerContainer.addEventListener('mouseup', () => this.mouseup());
        }
    };

    stop() {
        if (this._isRay) {
            this._isRay = false;
            this.viewerContainer.removeEventListener('click', e => this.ray(e));
            this.viewerContainer.removeEventListener('mousedown', () => this.mousedown());
            this.viewerContainer.removeEventListener('mouseup', () => this.mouseup());
        }
    };

    isRay() {
        return this._isRay;
    };

    mousedown() {
        this._mousedownPosition = { x: this.camera.position.x, y: this.camera.position.y, z: this.camera.position.z };
    }

    mouseup() {
        this._mouseupPosition = { x: this.camera.position.x, y: this.camera.position.y, z: this.camera.position.z };
    }

    ray(e) {
        let raycaster = this.createRaycaster(e.clientX, e.clientY);
        let objs = [];
        this.objects.map(object => {
            if (object.material.visible) {
                objs.push(object);
            }
        });
        let intersects = raycaster.intersectObjects(objs);
        if (intersects.length > 0) {
            let distance = utils.distance(this._mousedownPosition.x, this._mousedownPosition.y, this._mousedownPosition.z, this._mouseupPosition.x, this._mouseupPosition.y, this._mouseupPosition.z);

            if (distance < 5) {
                let result = [];
                intersects.map(intersect => {
                    if (intersect.object.name.indexOf(this.searchKey) >= 0) {
                        if (this.callback) {
                            result.push({ id: intersect.object.id, name: intersect.object.name, point: intersect.point, dataId: intersect.object.dataId, mesh: intersect.object });
                        }
                    }
                });
                if (result.length > 0) {
                    this.callback(result);
                }
            }
        }
    }

    createRaycaster(clientX, clientY) {
        let x = (clientX / $(this.viewerContainerId).width()) * 2 - 1;
        let y = -(clientY / $(this.viewerContainerId).height()) * 2 + 1;

        let standardVector = new THREE.Vector3(x, y, 0.5);

        let worldVector = standardVector.unproject(this.camera);

        let ray = worldVector.sub(this.camera.position).normalize();

        let raycaster = new THREE.Raycaster(this.camera.position, ray);

        return raycaster;
    }
}

export { Ray }
